﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Runtime.Remoting.Messaging;

namespace AsyncDelegateStudy
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("start");

            AsyncWorker worker = new AsyncWorker();
            worker.Dowork(13);

            Console.WriteLine("press enter to exit.");
            Console.ReadLine();
        }
    }

    // 定义被调用方法的delegate
    public delegate bool Workdele(int source, out int ithreadid);

    // 被调用方,封装被调用方法
    class Worker
    {
        public bool Dowork(int source, out int ithreadid)
        {
            ithreadid = AppDomain.GetCurrentThreadId();
            Console.WriteLine("my work starting in thread:{0}...", ithreadid);

            Thread.Sleep(5000);

            Console.WriteLine("my work ended in thread:{0}", ithreadid);
            return (source % 2) == 0;
        }
    }

    // 封装完成回调方法
    class ProcessWorkResult
    {
        public void CallbackMethod(IAsyncResult ar)
        {
            Console.WriteLine("callback int thread:{0}", AppDomain.GetCurrentThreadId());
            Workdele wd = (Workdele)((AsyncResult)ar).AsyncDelegate;
            int ithreadid;
            bool bret = wd.EndInvoke(out ithreadid, ar);
            Console.WriteLine("callback end: ithreadid={0} bret={1}", ithreadid, bret);
        }
    }

    // 调用方
    class AsyncWorker
    {
        public void Dowork(int source)
        {
            Worker worker = new Worker();
            Workdele wd = new Workdele(worker.Dowork);

            ProcessWorkResult wr = new ProcessWorkResult();
            AsyncCallback cb = new AsyncCallback(wr.CallbackMethod);

            Console.WriteLine("begin aync invoke...");
            int ithreadid;
            IAsyncResult ar = wd.BeginInvoke(source, out ithreadid, cb, (object)source);
            Thread.Sleep(0);
            Console.WriteLine("async invoke return.");
        }
    }
}
